﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;

namespace msdcp
{
    /// <summary>
    /// Special class for custom settings support.
    /// </summary>
    public class SettingsProvider
    {
        #region Private fields
        private static List<string> _settings;                  // The collection that stores all entries 
        // of the configuration file in memory.

        private static string _confFileName;                    // The name of the configuration file.

        private static string _initialText;                     // The string content of the configuration file that 
        // initializes it for the first time beeing used. 
        #endregion

        #region Private methods
        private static void ReadSettings()
        {
            if (_initialText.Length > 0)
            {
                using (StreamWriter sw = File.CreateText(Application.UserAppDataPath + _confFileName))
                {
                    sw.WriteLine(_initialText);
                    sw.Close();
                    sw.Dispose();
                }
            }
            using (StreamReader sr = File.OpenText(Application.UserAppDataPath + _confFileName))
            {
                while (!sr.EndOfStream)
                {
                    _settings.Add(sr.ReadLine());
                }
            }
        }

        /// <summary>
        /// Creates a new section in the existed settings file.
        /// The name of the section must be enclosed with square brackets.
        /// </summary>
        /// <param name="sectionName">The name of the new section</param>
        /// <param name="sectionContent">The string that represents a new section content.</param>
        private static void CreateSection(string sectionName, string sectionContent)
        {
            int placeToIns = _settings.IndexOf("[EndOfFile]");
            _settings.Insert(placeToIns, sectionName);
            placeToIns++;
            _settings.Insert(placeToIns, sectionContent);
        }

        /// <summary>
        /// Creates a new section in the existed settings file.
        /// The name of the section must be enclosed with square brackets.
        /// </summary>
        /// <param name="sectionName">The name of the new section</param>
        /// <param name="sectionContent">The string collection that represents a new section content.</param>
        private static void CreateSection(string sectionName, List<string> sectionContent)
        {
            int placeToIns = _settings.IndexOf("[EndOfFile]");
            _settings.Insert(placeToIns, sectionName);
            placeToIns++;
            _settings.InsertRange(placeToIns, sectionContent);
        } 
        #endregion

        #region Public methods
        /// <summary>
        /// Saves all settings from container in memory to a file 
        /// named "DA.conf" in current user application data directory.
        /// </summary>
        public static void WriteSettings()
        {
            using (StreamWriter sw = File.CreateText(Application.UserAppDataPath + _confFileName))
            {
                foreach (string s in _settings)
                {
                    sw.WriteLine(s);
                }
            }
        }

        /// <summary>
        /// Updates settings in a specified section of a settings file.
        /// </summary>
        /// <param name="sectionName">The name of a section in square brackets.</param>
        /// <param name="sectionContent">The content of whole section.</param>
        public static void UpdateSection(string sectionName, List<string> sectionContent)
        {
            int begin = _settings.IndexOf(sectionName);
            if (begin >= 0)
            {
                begin++;
                int end = _settings.FindIndex(begin, str => str.StartsWith("["));
                _settings.RemoveRange(begin, end - begin);
                _settings.InsertRange(begin, sectionContent);
            }
            else
            {
                CreateSection(sectionName, sectionContent);
            }
        }

        /// <summary>
        /// Inserts one string in a specified section at last position.
        /// </summary>
        /// <param name="sectionName">The name of a section in square brackets.</param>
        /// <param name="sectionContent">The string representation of setting to insert.</param>
        public static void UpdateSection(string sectionName, string sectionContent)
        {
            int begin = _settings.IndexOf(sectionName);
            if (begin >= 0)
            {
                begin++;
                int end = _settings.FindIndex(begin, str => str.StartsWith("["));
                _settings.Insert(end - 1, sectionContent);
            }
            else
            {
                CreateSection(sectionName, sectionContent);
            }
        }

        /// <summary>
        /// Gets the content of a specified section.
        /// </summary>
        /// <param name="sectionName">The name of a section in square brackets.</param>
        /// <returns>Collection with string representation of settings.</returns>
        public static List<string> GetSection(string sectionName)
        {
            List<string> result = new List<string>();
            int begin = _settings.IndexOf(sectionName);
            // If the section exists...
            if (begin >= 0)
            {
                begin++;
                int end = _settings.FindIndex(begin, str => str.StartsWith("["));
                result = _settings.GetRange(begin, end - begin);
            }
            else// if it doesn't...
            {
                CreateSection(sectionName, result);
            }
            return result;
        }

        /// <summary>
        /// Must be called before further use. Initializes 
        /// the internal settings container.
        /// </summary>
        public static void InitSet(string configFileName, string initialText)
        {
            _confFileName = "\\" + configFileName;
            _initialText = initialText;
            _settings = new List<string>();
            ReadSettings();
        } 
        #endregion
    }
}
